\section{Blade模版精要}
Blade 是 Laravel 提供的一个非常简单但很强大的模板引擎，不同于其他流行的 PHP 模板引擎，Blade 在视图中并不反对你使用 PHP 原生代码。所有的 Blade 视图都会被编译成原生 PHP 代码并缓存起来直到被修改，这意味着使用Blade模版，对应用的性能影响可以忽略。\cite{TaylorOtwell，2016a}

Blade 视图文件使用 .blade.php 文件扩展并存放在 resources/views 目录下。

Laravel 的 View 部分内置了两套输出系统：直接输出和使用 Blade 引擎“编译”后输出，默认情况下它们通过文件名后缀来选择：.blade.php 后缀的认为是模板视图文件，其他的 .php 文件按照 PHP 本身的方式执行。
\cite{刘小乐，2016}

模板引擎一般做三件事：
\begin{enumerate}
	\item 引入或继承其他文件
	\item 输出变量值
	\item 条件判断和循环（if ... else、for、foreach、while）
\end{enumerate}

Laravel 的模板引擎非常简洁，使用时并不需要掌握太多东西，基本上只需要知道以下两点：

\begin{enumerate}
	\item \{\{ 与 \}\} 之间是要输出的内容，也有扩展的两个方法 \{\{\{ ... \}\}\} 和 \{!! .. !!\} 分别用于转义输出和不转义输出，5.0 以后的版本中 \{\{ ... \}\} 之间的默认情况下也是转义输出的；
	\item @ 符号开头的都是指令，包括 PHP 本身有的 if else foreach 以及扩展的 include yield stop 等等。
\end{enumerate}

\subsection{引入与继承}
使用 Blade 的两个最大优点是模板继承（template inheritance）和区块（sections）。

\subsubsection{定义主模版}

大多数 Web 应用在不同页面中使用同一个布局，因此可以很方便的将这个布局定义为一个单独的 Blade 页面。假设下面的模版名为master.blade.php，保存在resources/views 目录下：

\begin{lstlisting}
<!DOCTYPE html>
<html>
    <head>
        <title>App Name - @yield('title')</title>
    </head>
    <body>
        @section('sidebar')
            This is the master sidebar.
        @show

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>
\end{lstlisting}

其中 @section 指令，用来定义一个内容的片段，而 @yield 指令用来显示给定片段的内容。@yield 是不可扩展的，如果你要定义的部分没有默认内容让子模板扩展的，那么用 @yield(\$name, \$default) 的形式会比较方便，如果你在子模板中并没有指定这个区块的内容，它就会显示默认内容，如果定义了，就会显示你定义的内容。非此即彼。与之相比， @section 则既可以被替代，又可以被扩展，这是最大的区别。\cite{junjie，2016}

与 @section 对应的结束关键字，@show, @stop 有什么区别呢？ @show 指的是执行到此处时将该 section 中的内容输出到页面，而 @stop 则只是进行内容解析，并且不再处理当前模板中后续对该section的处理，除非用 @override覆盖。通常来说，在首次定义某个 section 的时候，应该用 @show，而在替换它或者扩展它的时候，不应该用 @show，应该用 @stop。

\subsubsection{继承及扩展}
父页面定义了哪些区域需要填充，而子页面则需要指定将什么内容注入到什么区域。

定义子页面的时候，使用 @extends 指令来指定子页面所继承的布局，使用 @section 指令注入内容到布局的片段中，这些片段的内容将会显示在布局中使用 @yield 的地方。下面的模版名为child.blade.php，保存在 resources/views 目录下：

\begin{lstlisting}
@extends('master')

@section('title', '子页面标题')

@section('sidebar')
    @parent
    <p>这是从子页面追加到主页面的内容</p>
@endsection

@section('content')
    <p>这是子页面的内容</p>
@endsection
\end{lstlisting}

其中sidebar 片段使用 @parent 指令来追加（而非覆盖）内容到布局中 sidebar，@parent 指令在视图渲染时将会被布局中的内容替换。@section 对应的 @endsection 指令还可以替换为 @stop 指令。

设置好相应的路由后调用子视图，即可看到子视图实际输出的内容：

\begin{lstlisting}
这是主页面模版中的内容

这是从子页面追加到主页面的内容

这是子页面的内容
\end{lstlisting}

\subsection{显示数据}

\subsubsection{显示变量}
可以通过两个花括号包裹变量来显示传递到视图的数据，比如，如果给出如下控制器：
\begin{lstlisting}
	public function blade() {
		$title = '从变量传来的标题';
		$content = '变量内容';
		return view('child', compact('title', 'content'));
	}
\end{lstlisting}

子页面的内容如下：

\begin{lstlisting}
@extends('master')

@section('title', $title)

@section('sidebar')
    @parent
    <p>这是从子页面追加到主页面的内容</p>
@endsection

@section('content')
    <p>{{$content}}</p>
@endsection
\end{lstlisting}

在 blade 模版中的 HTML 中使用变量，则用 \{\{ ... \}\} 语法，而要在 @section 指令的参数部分，则使用正常的变量形式，正如上例中的@section('title', \$title)。

\begin{myremark}{\{\{ ... \}\} 语法的安全性}
Blade 的 \{\{ ... \}\} 语句已经经过 PHP 的 htmlentities 函数处理以避免 XSS 攻击。
\end{myremark}

\subsubsection{显示原生内容}
默认情况下，Blade 的 \{\{ ...\}\} 语句已经通过 PHP 的 htmlentities() 函数处理以避免 XSS 攻击，如果你不想要数据被处理，可以使用如下语法：

\begin{lstlisting}
{!! ... !!}
\end{lstlisting}

\subsection{控制结构}

Blade 还为常用的 PHP 流程控制提供了便利操作，比如条件语句和循环，这些快捷操作提供了一个干净、简单的方式来处理 PHP 的流程控制，同时保持和 PHP 相应语句的相似。

\subsubsection{分支语句}
可以使用 @if 、 @elseif 、  @else 和 @endif 来构造 if 语句，这些指令函数和 PHP 的相同。Blade 还提供了如下判断方式：

\begin{lstlisting}
{{ $name or 'Default' }}
\end{lstlisting}

为方便起见，Blade 还提供了 @unless 指令：

\begin{lstlisting}
@unless (Auth::check())
    You are not signed in.
@endunless
\end{lstlisting}

\subsubsection{循环语句}
Blade 还提供了简单指令处理 PHP 支持的循环结构，同样，这些指令函数和 PHP 的一样：
\begin{lstlisting}
@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor

@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach

@forelse ($users as $user)
    <li>{{ $user->name }}</li>
    @empty
    <p>No users</p>
@endforelse

@while (true)
    <p>I'm looping forever.</p>
@endwhile
\end{lstlisting}


